﻿#region COPYRIGHT
//--------------------------------------------------------------------------------
// <copyright file="Label.cs" company="starLiGHT Entertainment Studios">
//    Copyright (c) 2011 
//       Roland Rosenkranz (Glatzemann@email.de)
// </copyright>
// <license>
//   This file is part of starLiGHT.GUI.
//
//   It is released under the Microsoft Public License (Ms-PL).
//
//   You should have received a copy of the Microsoft Public License
//   along with starLiGHT.GUI. If not, see http://sle.codeplex.com/license.
//    
//   ADDITIONAL (commercial) LICENSES for starLiGHT.GUI are available on request.
// </license>
// <version>
// **************[ starLiGHT.Engine SVN ]**********************
// * $Rev::                       $:  Revision of last commit *
// * $Author::                    $:  Author of last commit   *
// * $Date::                      $:  Date of last commit     *
// ************************************************************
// </version>
//--------------------------------------------------------------------------------
#endregion

namespace starLiGHT.GUI.Widgets
{
#region Using Statements
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;
    using starLiGHT.Collections;
#endregion

    public class Label : Widget
    {
        private bool wrapText;
        private float clauseSpacing;

        // used for wraped text (multiline)
        // clauses and lines has to be separated to visualize justified text correctly.
        private FastList<List<string>> clausesAndLines = new FastList<List<string>>();

        #region Constructors
        public Label(GuiManager manager, string name)
            : base(manager, name)
        {
        }

        public Label(GuiManager manager, string name, string layout)
            : base(manager, name, layout)
        {
        }
        #endregion

        public override RectangleF ClientRectangle
        {
            get
            {
                RectangleF clientRectangle = this.DisplayRectangle;
                clientRectangle.Inflate(-2f, -2f);
                return clientRectangle;
            }
        }

        public override bool CanFocus
        {
            get
            {
                return false;
            }
        }

        public bool WrapText
        {
            get
            {
                return this.wrapText;
            }

            set
            {
                this.wrapText = value;
                this.CacheText(this.Text);
            }
        }

        public override string Text
        {
            get
            {
                return base.Text;
            }

            set
            {
                base.Text = value;
                this.CacheText(value);
            }
        }

        public float ClauseExtraSpacing
        {
            get
            {
                return this.clauseSpacing;
            }

            set
            {
                this.clauseSpacing = value;
            }
        }

        public override void DrawText(IGuiRenderer renderer, Layer layer, TextLabel te)
        {
            float spacing = Font.Spacing;

            if (this.wrapText)
            {
                int idx = 0;
                for (int clause = 0; clause < this.clausesAndLines.Count; clause++)
                {
                    for (int line = 0; line < this.clausesAndLines[clause].Count; line++)
                    {
                        string text = this.clausesAndLines[clause][line];
                        if (TextAlignment == GUI.TextAlignment.Justify)
                        {
                            if (line < this.clausesAndLines[clause].Count - 1)
                            {
                                float space = this.ClientRectangle.Width - Font.MeasureString(text).X;
                                Font.Spacing += space / text.Length;
                            }
                            else
                            {
                                Font.Spacing = spacing;
                            }
                        }

                        renderer.DrawString(Font, text, GetTextPosition(text, TextAlignment, idx++, clause * this.clauseSpacing), ForeColor);
                    }
                }
            }
            else
            {
                if (TextAlignment == GUI.TextAlignment.Justify)
                {
                    float space = this.ClientRectangle.Width - Font.MeasureString(this.Text).X;
                    Font.Spacing += space / this.Text.Length;
                }

                renderer.DrawString(Font, this.Text, GetTextPosition(this.Text, TextAlignment, 0, 0), ForeColor);
            }

            Font.Spacing = spacing;
        }

        private void CacheText(string text)
        {
            this.clausesAndLines.Clear();

            if (!this.wrapText)
            {
                return;
            }

            string[] clauses = text.Split('\n', '\r');
            if (clauses.Length == 0)
            {
                return;
            }

            foreach (string clause in clauses)
            {
                string[] words = clause.Split(' ');

                List<string> tmp = new List<string>();
                tmp.Add(string.Empty);

                float spaceLength = Font.MeasureString(" ").X + (2 * Font.Spacing);
                float lineLength = 0;

                for (int i = 0; i < words.Length; i++)
                {
                    float len = spaceLength + Font.MeasureString(words[i]).X;

                    if (lineLength + len > this.ClientRectangle.Width && tmp[tmp.Count - 1].Length > 0)
                    {
                        tmp[tmp.Count - 1] = tmp[tmp.Count - 1].TrimEnd();
                        tmp.Add(string.Empty);
                        lineLength = 0;
                    }

                    tmp[tmp.Count - 1] += words[i] + " ";
                    lineLength += len;
                }

                this.clausesAndLines.Add(tmp);
            }
        }
    }
}
